/**
 *
 */
package com.angel.data.generator.builders;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.apache.log4j.Logger;

import com.angel.data.generator.base.DataGeneratorRunner;
import com.angel.data.generator.builders.impl.DataGeneratorRunnerImplBuilder;
import com.angel.data.generator.checkers.DataGeneratorChecker;
import com.angel.data.generator.checkers.DataGeneratorCheckerRunner;
import com.angel.data.generator.checkers.impl.InverseDependenceDataGeneratorChecker;
import com.angel.data.generator.checkers.impl.NullDataGeneratorChecker;
import com.angel.data.generator.preProcess.PreProcessStrategy;
import com.angel.data.generator.validators.DataGeneratorBuilderValidator;

/**
 *
 * @author William
 * @since 21/August/2009.
 *
 */
public abstract class DataGeneratorRunnerBuilder {

    /**
     * Logger class.
     */
    private static Logger LOGGER = Logger.getLogger(DataGeneratorRunnerImplBuilder.class);
    /**
     * Check runner for check all data generator classes to add to this process.
     */
    private DataGeneratorCheckerRunner checkerRunner = new DataGeneratorCheckerRunner();

    private PreProcessStrategy preProcessStrategy;

	private List<DataGeneratorBuilderValidator> builderValidators;

    public DataGeneratorRunnerBuilder(){
        super();
        this.addDataGeneratorChecker(new NullDataGeneratorChecker());
        this.addDataGeneratorChecker(new InverseDependenceDataGeneratorChecker());
        this.setBuilderValidators(new ArrayList<DataGeneratorBuilderValidator>());
        this.initializeValidators();
    }

    public DataGeneratorRunnerBuilder(Collection<DataGeneratorChecker> dataGeneratorCheckers){
        this();
        this.getCheckerRunner().addAllChecker(dataGeneratorCheckers);
    }

    public DataGeneratorRunnerBuilder(Collection<DataGeneratorChecker> dataGeneratorCheckers, PreProcessStrategy preProcessStrategy){
        this(dataGeneratorCheckers);
        this.setPreProcessStrategy(preProcessStrategy);
    }


    protected abstract void initializeValidators();

    public abstract DataGeneratorRunner buildDataGeneratorRunner();

    public abstract <T> void addDataGeneratorClass(Class<T> dataGeneratorClass);

    public void addDataGeneratorChecker(DataGeneratorChecker dataGeneratorChecker){
    	this.getCheckerRunner().addChecker(dataGeneratorChecker);
    }

    public void addDataGeneratorCheckers(Collection<DataGeneratorChecker> dataGeneratorCheckers){
    	this.getCheckerRunner().addAllChecker(dataGeneratorCheckers);
    }

	/**
	 * @return the checkerRunner
	 */
	public DataGeneratorCheckerRunner getCheckerRunner() {
		return checkerRunner;
	}

	/**
	 * @param checkerRunner the checkerRunner to set
	 */
	public void setCheckerRunner(DataGeneratorCheckerRunner checkerRunner) {
		this.checkerRunner = checkerRunner;
	}

	/**
	 * @return the preProcessStrategy
	 */
	public PreProcessStrategy getPreProcessStrategy() {
		return preProcessStrategy;
	}

	/**
	 * @param preProcessStrategy the preProcessStrategy to set
	 */
	public void setPreProcessStrategy(PreProcessStrategy preProcessStrategy) {
		this.preProcessStrategy = preProcessStrategy;
	}

	 protected <T> void validateDataGeneratorClass(Class<T> dataGeneratorClass) {
	    	LOGGER.info("Validating data generator class [" + dataGeneratorClass.getName() + "].");
	    	for(DataGeneratorBuilderValidator validator: builderValidators){
	    		validator.validate(dataGeneratorClass);
	    	}
	    }

	    public void addDataGeneratorBuilderValidator(DataGeneratorBuilderValidator annotationValidator){
	    	this.getBuilderValidators().add(annotationValidator);
	    }

	    public void removeDataGeneratorBuilderValidator(DataGeneratorBuilderValidator annotationValidator){
	    	this.getBuilderValidators().remove(annotationValidator);
	    }

	    public boolean containsDataGeneratorBuilderValidator(DataGeneratorBuilderValidator annotationValidator){
	    	return this.getBuilderValidators().contains(annotationValidator);
	    }

		/**
		 * @return the builderValidators
		 */
		public List<DataGeneratorBuilderValidator> getBuilderValidators() {
			return builderValidators;
		}

		/**
		 * @param builderValidators the builderValidators to set
		 */
		public void setBuilderValidators(
				List<DataGeneratorBuilderValidator> builderValidators) {
			this.builderValidators = builderValidators;
		}
}
